home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 42
/
Amiga Format AFCD42 (Issue 126, Aug 1999).iso
/
-serious-
/
programming
/
other
/
jikes
/
src
/
symbol.h
< prev
next >
Wrap
C/C++ Source or Header
|
1999-05-14
|
73KB
|
2,293 lines
// $Id: symbol.h,v 1.11 1999/03/09 14:37:17 shields Exp $
//
// This software is subject to the terms of the IBM Jikes Compiler
// License Agreement available at the following URL:
// http://www.ibm.com/research/jikes.
// Copyright (C) 1996, 1998, International Business Machines Corporation
// and others. All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
#ifndef symbol_INCLUDED
#define symbol_INCLUDED
#include "config.h"
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include "code.h"
#include "stream.h"
#include "option.h"
#include "lookup.h"
#include "depend.h"
#include "access.h"
#include "tuple.h"
class Semantic;
class SemanticEnvironment;
class Ast;
class AstCompilationUnit;
class AstMethodDeclarator;
class AstBlock;
class AstList;
class AstExpression;
class AstVariableDeclarator;
class ExpandedTypeTable;
class ExpandedFieldTable;
class ExpandedMethodTable;
class SymbolTable;
class SymbolSet;
class Zip;
class PackageSymbol;
class PathSymbol : public Symbol
{
public:
NameSymbol *name_symbol;
Zip *zipfile;
PathSymbol(NameSymbol *);
virtual ~PathSymbol();
virtual wchar_t *Name() { return name_symbol -> Name(); }
virtual int NameLength() { return name_symbol -> NameLength(); }
virtual NameSymbol *Identity() { return name_symbol; }
char *Utf8Name() { return (char *) (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL); }
int Utf8NameLength() { return (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0); }
inline bool IsZip() { return zipfile != NULL; }
inline DirectorySymbol *RootDirectory() { return root_directory; }
private:
friend class SymbolTable;
DirectorySymbol *root_directory;
};
class DirectorySymbol : public Symbol
{
public:
Symbol *owner;
NameSymbol *name_symbol;
Tuple<DirectorySymbol *> subdirectories;
DirectorySymbol(NameSymbol *, Symbol *);
virtual ~DirectorySymbol();
virtual wchar_t *Name() { return name_symbol -> Name(); }
virtual int NameLength() { return name_symbol -> NameLength(); }
virtual NameSymbol *Identity() { return name_symbol; }
char *Utf8Name() { return (char *) (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL); }
int Utf8NameLength() { return (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0); }
DirectoryEntry *FindEntry(char *name, int len) { return (entries ? entries -> FindEntry(name, len) : (DirectoryEntry *) NULL); }
#ifdef WIN32_FILE_SYSTEM
DirectoryEntry *FindCaseInsensitiveEntry(char *name, int length)
{
return entries -> FindCaseInsensitiveEntry(name, length);
}
void InsertEntry(char *name, int length)
{
DirectoryEntry *entry = entries -> InsertEntry((DirectorySymbol *) this, name, length);
entries -> InsertCaseInsensitiveEntry(entry);
return;
}
#endif
PathSymbol *PathSym()
{
return (owner -> PathCast() ? (PathSymbol *) owner : ((DirectorySymbol *) owner) -> PathSym());
}
inline bool IsZip() { return PathSym() -> IsZip(); }
void SetDirectoryName();
inline char *DirectoryName()
{
if (! directory_name)
SetDirectoryName();
return directory_name;
}
inline int DirectoryNameLength()
{
if (! directory_name)
SetDirectoryName();
return directory_name_length;
}
inline DirectorySymbol *InsertDirectorySymbol(NameSymbol *);
inline DirectorySymbol *InsertAndReadDirectorySymbol(NameSymbol *);
inline DirectorySymbol *FindDirectorySymbol(NameSymbol *);
inline FileSymbol *InsertFileSymbol(NameSymbol *);
inline FileSymbol *FindFileSymbol(NameSymbol *);
void ResetDirectory();
private:
time_t mtime;
void ReadDirectory();
SymbolTable *table;
inline SymbolTable *Table();
DirectoryTable *entries;
char *directory_name;
int directory_name_length;
};
class FileSymbol : public Symbol
{
private:
enum FileKind
{
JAVA,
CLASS,
CLASS_ONLY
};
DirectorySymbol *output_directory;
char *file_name;
int file_name_length;
public:
NameSymbol *name_symbol;
DirectorySymbol *directory_symbol;
PackageSymbol *package;
FileKind kind;
//
// These fields are used for files in zip packages.
//
u4 uncompressed_size;
u4 date_time;
long offset;
//
// This field holds the time of last data modification for a non-zip file
//
time_t mtime;
LexStream *lex_stream;
AstCompilationUnit *compilation_unit;
Semantic *semantic;
Tuple<TypeSymbol *> types;
FileSymbol(NameSymbol *name_symbol_, NameSymbol *dirname_symbol = NULL) : name_symbol(name_symbol_),
output_directory(NULL),
directory_symbol(NULL),
package(NULL),
file_name(NULL),
mtime(0),
lex_stream(NULL),
compilation_unit(NULL),
semantic(NULL),
types(4)
{
Symbol::_kind = _FILE;
}
virtual ~FileSymbol()
{
delete [] file_name;
delete lex_stream;
}
FileSymbol *Clone()
{
FileSymbol *clone = new FileSymbol(name_symbol);
clone -> kind = kind;
clone -> directory_symbol = directory_symbol;
clone -> mtime = mtime;
return clone;
}
virtual wchar_t *Name() { return name_symbol -> Name(); }
virtual int NameLength() { return name_symbol -> NameLength(); }
virtual NameSymbol *Identity() { return name_symbol; }
char *Utf8Name() { return (char *) (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL); }
int Utf8NameLength() { return (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0); }
inline void SetJava() { kind = JAVA; }
inline void SetClass() { kind = CLASS; }
inline void SetClassOnly() { kind = CLASS_ONLY; }
inline bool IsJava() { return kind == JAVA; }
inline bool IsClass() { return kind >= CLASS; }
inline bool IsClassOnly() { return kind == CLASS_ONLY; }
PathSymbol *PathSym()
{
return directory_symbol -> PathSym();
}
inline bool IsZip() { return PathSym() -> IsZip(); }
inline Zip *Zipfile() { return PathSym() -> zipfile; }
static char *java_suffix;
static int java_suffix_length;
static char *class_suffix;
static int class_suffix_length;
static inline bool IsJavaSuffix(char *ptr);
static inline bool IsClassSuffix(char *ptr);
inline char *FileName()
{
if (! file_name)
SetFileName();
return file_name;
}
inline int FileNameLength()
{
if (! file_name)
SetFileName();
return file_name_length;
}
DirectorySymbol *OutputDirectory();
void SetFileName();
void CleanUp();
void Reset()
{
CleanUp();
delete [] file_name;
file_name = NULL;
types.Reset();
}
};
class FileLocation
{
public:
wchar_t *location;
FileLocation (LexStream *lex_stream, LexStream::TokenIndex token_index)
{
char *file_name = lex_stream -> FileName();
int length = lex_stream -> FileNameLength();
location = new wchar_t[length + 13];
for (int i = 0; i < length; i++) {
location[i] = (wchar_t) file_name[i];
}
location[length++] = U_COLON;
char str[13];
sprintf(str, "%i", lex_stream -> Line(token_index));
for (int j = 0; str[j]; j++)
location[length++] = str[j];
location[length] = U_NULL;
return;
}
FileLocation (FileSymbol *file_symbol)
{
char *file_name = file_symbol -> FileName();
int length = file_symbol -> FileNameLength();
location = new wchar_t[length + 13];
for (int i = 0; i < length; i++) {
location[i] = (wchar_t) file_name[i];
}
location[length] = U_NULL;
return;
}
~FileLocation()
{
delete [] location;
}
};
class PackageSymbol : public Symbol
{
public:
Tuple<DirectorySymbol *> directory;
PackageSymbol *owner;
PackageSymbol(NameSymbol *name_symbol_, PackageSymbol *owner_) : name_symbol(name_symbol_),
directory(4),
owner(owner_),
package_name(NULL),
table(NULL)
{
Symbol::_kind = PACKAGE;
}
virtual ~PackageSymbol();
virtual wchar_t *Name() { return name_symbol -> Name(); }
virtual int NameLength() { return name_symbol -> NameLength(); }
virtual NameSymbol *Identity() { return name_symbol; }
char *Utf8Name() { return (char *) (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL); }
int Utf8NameLength() { return (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0); }
void SetPackageName();
wchar_t *PackageName()
{
if (! package_name)
SetPackageName();
return package_name;
}
int PackageNameLength()
{
if (! package_name)
SetPackageName();
return package_name_length;
}
inline PackageSymbol *FindPackageSymbol(NameSymbol *);
inline PackageSymbol *InsertPackageSymbol(NameSymbol *);
inline TypeSymbol *FindTypeSymbol(NameSymbol *);
inline TypeSymbol *InsertSystemTypeSymbol(NameSymbol *);
inline TypeSymbol *InsertOuterTypeSymbol(NameSymbol *);
inline void DeleteTypeSymbol(TypeSymbol *);
private:
NameSymbol *name_symbol;
SymbolTable *table;
inline SymbolTable *Table();
wchar_t *package_name;
int package_name_length;
};
class MethodSymbol : public Symbol, public AccessFlags
{
public:
Ast *method_or_constructor_declaration; // AstMethodDeclaration or AstConstructorDeclaration
NameSymbol *name_symbol;
TypeSymbol *containing_type;
BlockSymbol *block_symbol;
MethodSymbol *next_method;
Utf8LiteralValue *signature;
//
// If this method is a method that is generated in order to process initializer
// blocks contained in the body of a class, it needs to know the set of
// constructors that might invoke it in order to figure out which exceptions
// can be safely thrown within an initializer block.
//
int NumInitializerConstructors()
{
return (initializer_constructors ? initializer_constructors -> Length() : 0);
}
MethodSymbol *InitializerConstructor(int i)
{
return (*initializer_constructors)[i];
}
void AddInitializerConstructor(MethodSymbol *method)
{
if (! initializer_constructors)
initializer_constructors = new Tuple<MethodSymbol *>(8);
initializer_constructors -> Next() = method;
}
int max_block_depth,
constant_pool_index,
constant_pool_class;
//
// If the method in question is a private member, we may need to construct
// another method that allows it to be accessed by inner classes.
//
MethodSymbol *read_method;
//
// If this method is a method that permits access to a private member of an
// enclosing type then accessed_member identifies the member in question.
//
Symbol *accessed_member;
virtual wchar_t *Name() { return name_symbol -> Name(); }
virtual int NameLength() { return name_symbol -> NameLength(); }
virtual NameSymbol *Identity() { return name_symbol; }
char *Utf8Name() { return (char *) (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL); }
int Utf8NameLength() { return (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0); }
MethodSymbol(NameSymbol *name_symbol_) : method_or_constructor_declaration(NULL),
name_symbol(name_symbol_),
external_name_symbol(NULL),
containing_type(NULL),
block_symbol(NULL),
next_method(NULL),
signature(NULL),
type_(NULL),
status(0),
header(NULL),
max_block_depth(1), // there must be at least one block in a method
// this default is useful for default constructors.
constant_pool_index(0),
constant_pool_class(0),
local_constructor(NULL),
read_method(NULL),
accessed_member(NULL),
formal_parameters(NULL),
throws(NULL),
throws_signatures(NULL),
initializer_constructors(NULL)
{
Symbol::_kind = METHOD;
}
virtual ~MethodSymbol();
bool IsFinal();
bool IsTyped()
{
return type_ != NULL;
}
void SetType(TypeSymbol *_type)
{
type_ = _type;
}
void ProcessMethodSignature(Semantic *, LexStream::TokenIndex);
void ProcessMethodThrows(Semantic *, LexStream::TokenIndex);
TypeSymbol *Type(Semantic *sem = NULL, LexStream::TokenIndex tok = 0)
{
if (! type_)
ProcessMethodSignature(sem, tok);
assert(type_);
return type_;
}
int NumFormalParameters(Semantic *sem = NULL, LexStream::TokenIndex tok = 0)
{
if (! type_)
ProcessMethodSignature(sem, tok);
assert(type_);
return (formal_parameters ? formal_parameters -> Length() : 0);
}
VariableSymbol *FormalParameter(int i)
{
return (*formal_parameters)[i];
}
void AddFormalParameter(VariableSymbol *variable)
{
if (! formal_parameters)
formal_parameters = new Tuple<VariableSymbol *>(8);
formal_parameters -> Next() = variable;
}
int NumThrows(Semantic *sem = NULL, LexStream::TokenIndex tok = 0)
{
if (throws_signatures)
ProcessMethodThrows(sem, tok);
assert(! throws_signatures);
return (throws ? throws -> Length() : 0);
}
TypeSymbol *Throws(int i)
{
return (*throws)[i];
}
void AddThrows(TypeSymbol *exception)
{
if (! throws)
throws = new Tuple<TypeSymbol *>(8);
throws -> Next() = exception;
}
int NumThrowsSignatures()
{
return (throws_signatures ? throws_signatures -> Length() : 0);
}
char *ThrowsSignature(int i)
{
return (*throws_signatures)[i];
}
void AddThrowsSignature(char *signature_, int length)
{
char *signature = new char[length + 1];
strncpy(signature, signature_, length);
signature[length] = U_NULL;
if (! throws_signatures)
throws_signatures = new Tuple<char *>(8);
throws_signatures -> Next() = signature;
}
void SetGeneratedLocalConstructor(MethodSymbol *base_method)
{
assert(! base_method -> local_constructor);
base_method -> local_constructor = this;
this -> local_constructor = base_method;
}
bool IsGeneratedLocalConstructor() { return ((local_constructor != NULL) && (this -> external_name_symbol == NULL)); }
MethodSymbol *LocalConstructor() { return local_constructor; }
void SetExternalIdentity(NameSymbol *external_name_symbol_) { external_name_symbol = external_name_symbol_; }
NameSymbol *ExternalIdentity()
{
return (external_name_symbol ? external_name_symbol : name_symbol);
}
wchar_t *ExternalName()
{
return (external_name_symbol ? external_name_symbol -> Name() : name_symbol -> Name());
}
int ExternalNameLength()
{
return (external_name_symbol ? external_name_symbol -> NameLength() : name_symbol -> NameLength());
}
char *ExternalUtf8Name()
{
return (char *) (external_name_symbol ? external_name_symbol -> Utf8_literal -> value
: (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL));
}
int ExternalUtf8NameLength()
{
return (external_name_symbol ? (external_name_symbol -> Utf8_literal ? external_name_symbol -> Utf8_literal -> length : 0)
: (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0));
}
void SetFlags(AccessFlags variable_access) { access_flags = variable_access.access_flags; }
void SetContainingType(TypeSymbol *containing_type_) { containing_type = containing_type_; }
void SetBlockSymbol(BlockSymbol *block_symbol_) { block_symbol = block_symbol_; }
void SetSignature(Control &, VariableSymbol * = NULL);
void SetSignature(Utf8LiteralValue *signature_) { signature = signature_; }
char *SignatureString() { return signature -> value; }
wchar_t *Header(Semantic * = NULL, LexStream::TokenIndex = 0);
void CleanUp();
void MarkSynthetic() { status |= (unsigned char) 0x08; }
bool IsSynthetic() { return status & (unsigned char) 0x08; }
private:
NameSymbol *external_name_symbol;
unsigned char status;
wchar_t *header;
TypeSymbol *type_;
Tuple<VariableSymbol *> *formal_parameters;
Tuple<TypeSymbol *> *throws;
Tuple<char *> *throws_signatures;
Tuple<MethodSymbol *> *initializer_constructors;
//
// If the method in question is a constructor of a local type, we may need to construct
// another constructor that accepts extra local parameters.
//
MethodSymbol *local_constructor;
bool ACC_FINAL()
{
assert(! "use the ACC_FINAL() flag on a method symbol. Use the function IsFinal() instead");
return false;
}
};
class TypeSymbol : public Symbol, public AccessFlags
{
public:
SemanticEnvironment *semantic_environment;
Ast *declaration; // AstClassDeclaration or AstInterfaceDeclaration
FileSymbol *file_symbol;
FileLocation *file_location;
NameSymbol *name_symbol;
Symbol *owner;
TypeSymbol *outermost_type; // An nested class identifies the outer most type that contains it.
// If a class is not nested then it identifies itself as its outer
// most type.
TypeSymbol *super;
TypeSymbol *base_type; // indicates the base type (type of elements in the last dimension) of an array
// For a normal type base_type is NULL. If base_type is a "bad" type it points
// to itsself (this).
int index, // The first two variables is used in TypeCycleChecker to determine if this class or interface
// forms a cycle in its "extends" or "implements" relationship.
incremental_index; // This variable is used in TypeCycleChecker to determine which types (files)
// need to be recompiled based on the "dependent" relationship.
int NumLocalConstructorCallEnvironments() { return (local_constructor_call_environments ? local_constructor_call_environments -> Length() : 0); }
SemanticEnvironment *&LocalConstructorCallEnvironment(int i) { return (*local_constructor_call_environments)[i]; }
void AddLocalConstructorCallEnvironment(SemanticEnvironment *environment)
{
if (! local_constructor_call_environments)
local_constructor_call_environments = new Tuple<SemanticEnvironment *>(8);
local_constructor_call_environments -> Next() = environment;
}
int NumPrivateAccessMethods() { return (private_access_methods ? private_access_methods -> Length() : 0); }
MethodSymbol *&PrivateAccessMethod(int i) { return (*private_access_methods)[i]; }
void AddPrivateAccessMethod(MethodSymbol *method_symbol)
{
if (! private_access_methods)
private_access_methods = new Tuple<MethodSymbol *>(8);
private_access_methods -> Next() = method_symbol;
}
int NumPrivateAccessConstructors() { return (private_access_constructors ? private_access_constructors -> Length() : 0); }
MethodSymbol *&PrivateAccessConstructor(int i) { return (*private_access_constructors)[i]; }
void AddPrivateAccessConstructor(MethodSymbol *constructor_symbol)
{
if (! private_access_constructors)
private_access_constructors = new Tuple<MethodSymbol *>(8);
private_access_constructors -> Next() = constructor_symbol;
}
int NumConstructorParameters() { return (constructor_parameters ? constructor_parameters -> Length() : 0); }
VariableSymbol *&ConstructorParameter(int i) { return (*constructor_parameters)[i]; }
void AddConstructorParameter(VariableSymbol *variable_symbol)
{
if (! constructor_parameters)
constructor_parameters = new Tuple<VariableSymbol *>(8);
constructor_parameters -> Next() = variable_symbol;
}
int NumGeneratedConstructors() { return (generated_constructors ? generated_constructors -> Length() : 0); }
MethodSymbol *&GeneratedConstructor(int i) { return (*generated_constructors)[i]; }
void AddGeneratedConstructor(MethodSymbol *constructor_symbol)
{
if (! generated_constructors)
generated_constructors = new Tuple<MethodSymbol *>(8);
generated_constructors -> Next() = constructor_symbol;
}
int NumEnclosingInstances() { return (enclosing_instances ? enclosing_instances -> Length() : 0); }
VariableSymbol *&EnclosingInstance(int i) { return (*enclosing_instances)[i]; }
void AddEnclosingInstance(VariableSymbol *instance_symbol)
{
if (! enclosing_instances)
enclosing_instances = new Tuple<VariableSymbol *>(8);
enclosing_instances -> Next() = instance_symbol;
}
int NumClassLiterals() { return (class_literals ? class_literals -> Length() : 0); }
VariableSymbol *&ClassLiteral(int i) { return (*class_literals)[i]; }
void AddClassLiteral(VariableSymbol *literal_symbol)
{
if (! class_literals)
class_literals = new Tuple<VariableSymbol *>(8);
class_literals -> Next() = literal_symbol;
}
int NumNestedTypes() { return (nested_types ? nested_types -> Length() : 0); }
TypeSymbol *&NestedType(int i) { return (*nested_types)[i]; }
void AddNestedType(TypeSymbol *type_symbol)
{
if (! nested_types)
nested_types = new Tuple<TypeSymbol *>(8);
nested_types -> Next() = type_symbol;
}
int NumInterfaces() { return (interfaces ? interfaces -> Length() : 0); }
void ResetInterfaces()
{
delete interfaces;
interfaces = NULL;
}
TypeSymbol *Interface(int i) { return (*interfaces)[i]; }
void AddInterface(TypeSymbol *type_symbol)
{
if (! interfaces)
interfaces = new Tuple<TypeSymbol *>(8);
interfaces -> Next() = type_symbol;
}
int num_anonymous_types() { return (anonymous_types ? anonymous_types -> Length() : 0); }
TypeSymbol *&AnonymousType(int i) { return (*anonymous_types)[i]; }
void AddAnonymousType(TypeSymbol *type_symbol)
{
if (! anonymous_types)
anonymous_types = new Tuple<TypeSymbol *>(8);
anonymous_types -> Next() = type_symbol;
}
void DeleteAnonymousTypes();
SymbolSet *local,
*non_local;
SymbolSet *supertypes_closure,
*subtypes,
*subtypes_closure,
*innertypes_closure;
SymbolSet *dependents,
*parents,
*dependents_closure, // processed in cycle.cpp
*parents_closure; // processed in cycle.cpp
int pool_index; // index of element in symbol_pool (in the relevant symbol table) that points to this type
Utf8LiteralValue *signature;
Utf8LiteralValue *fully_qualified_name;
ExpandedTypeTable *expanded_type_table;
ExpandedFieldTable *expanded_field_table;
ExpandedMethodTable *expanded_method_table;
int num_dimensions;
MethodSymbol *static_initializer_method;
MethodSymbol *block_initializer_method;
virtual wchar_t *Name() { return name_symbol -> Name(); }
virtual int NameLength() { return name_symbol -> NameLength(); }
virtual NameSymbol *Identity() { return name_symbol; }
char *Utf8Name() { return (char *) (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL); }
int Utf8NameLength() { return (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0); }
void SetExternalIdentity(NameSymbol *external_name_symbol_) { external_name_symbol = external_name_symbol_; }
NameSymbol *ExternalIdentity()
{
return (external_name_symbol ? external_name_symbol : name_symbol);
}
wchar_t *ExternalName()
{
return (external_name_symbol ? external_name_symbol -> Name() : name_symbol -> Name());
}
int ExternalNameLength()
{
return (external_name_symbol ? external_name_symbol -> NameLength() : name_symbol -> NameLength());
}
char *ExternalUtf8Name()
{
return (char *) (external_name_symbol ? external_name_symbol -> Utf8_literal -> value
: (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL));
}
int ExternalUtf8NameLength()
{
return (external_name_symbol ? (external_name_symbol -> Utf8_literal ? external_name_symbol -> Utf8_literal -> length : 0)
: (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0));
}
TypeSymbol(NameSymbol *);
virtual ~TypeSymbol();
void ProcessTypeHeaders();
void ProcessMembers();
void CompleteSymbolTable();
void ProcessExecutableBodies();
void RemoveCompilationReferences();
NameSymbol *GetThisName(Control &, int);
VariableSymbol *FindThis(int k)
{
assert(IsInner());
assert(NumConstructorParameters() > 0);
return (k == 0 ? ConstructorParameter(0)
: (VariableSymbol *) (NumEnclosingInstances() > k ? EnclosingInstance(k) : NULL));
}
VariableSymbol *InsertThis(int k);
TypeSymbol *FindOrInsertClassLiteralClass(LexStream::TokenIndex);
TypeSymbol *ClassLiteralClass()
{
return class_literal_class;
}
MethodSymbol *FindOrInsertClassLiteralMethod(Control &);
MethodSymbol *ClassLiteralMethod()
{
return class_literal_method;
}
Utf8LiteralValue *FindOrInsertClassLiteralName(Control &);
Utf8LiteralValue *ClassLiteralName()
{
return class_literal_name;
}
VariableSymbol *FindOrInsertClassLiteral(TypeSymbol *);
VariableSymbol *FindOrInsertLocalShadow(VariableSymbol *);
static MethodSymbol *GetReadAccessMethod(MethodSymbol *);
static MethodSymbol *GetReadAccessMethod(VariableSymbol *);
static MethodSymbol *GetWriteAccessMethod(VariableSymbol *);
bool IsArray() { return (num_dimensions > 0); }
void SetOwner(Symbol *owner_) { owner = owner_; }
bool IsOwner(TypeSymbol *type)
{
Symbol *sym = type -> owner;
while (! sym -> PackageCast())
{
if (sym == this)
return true;
MethodSymbol *method = sym -> MethodCast();
sym = (method ? method -> containing_type : ((TypeSymbol *) sym) -> owner);
}
return false;
}
TypeSymbol *ContainingType()
{
if (owner)
{
TypeSymbol *type = owner -> TypeCast();
if (type)
return type;
MethodSymbol *method = owner -> MethodCast();
if (method)
return method -> containing_type;
}
return NULL;
}
bool CanAccess(TypeSymbol *);
bool HasProtectedAccessTo(TypeSymbol *);
bool IsSubclass(TypeSymbol *super_class)
{
return (this == super_class ? true : (super == NULL ? false : super -> IsSubclass(super_class)));
}
bool IsSubinterface(TypeSymbol *super_interface)
{
if (this == super_interface)
return true;
for (int i = 0; i < NumInterfaces(); i++)
{
if (Interface(i) -> IsSubinterface(super_interface))
return true;
}
return false;
}
bool Implements(TypeSymbol *inter)
{
for (int i = 0; i < NumInterfaces(); i++)
{
if (Interface(i) -> IsSubinterface(inter))
return true;
}
return (this -> super ? this -> super -> Implements(inter) : false);
}
wchar_t *FileLoc()
{
return (wchar_t *) (file_location ? file_location -> location : NULL);
}
void SetLocation();
TypeSymbol *GetArrayType(Semantic *, int);
TypeSymbol *ArraySubtype()
{
return this -> base_type -> Array(this -> num_dimensions - 1);
}
void SetSignature(Control &);
void SetSignature(Utf8LiteralValue *signature_) { signature = signature_; }
char *SignatureString() { return signature -> value; }
void SetClassLiteralName(Utf8LiteralValue *class_literal_name_) { class_literal_name = class_literal_name_; }
PackageSymbol *ContainingPackage() { return outermost_type -> owner -> PackageCast(); }
void SetFlags(AccessFlags variable_access) { access_flags = variable_access.access_flags; }
bool IsNestedIn(TypeSymbol *);
bool IsNested() { return outermost_type != this; }
bool IsTopLevel() { return (! IsNested()) || this -> ACC_STATIC(); }
bool IsInner() { return (! IsTopLevel()); }
bool IsLocal()
{
for (Symbol *sym = owner; ! sym -> PackageCast(); sym = ((TypeSymbol *) sym) -> owner)
{
if (sym -> MethodCast())
return true;
}
return false;
}
inline char *ClassName()
{
if (! class_name)
SetClassName();
return class_name;
}
void MarkConstructorMembersProcessed() { status |= (unsigned short) 0x0001; }
bool ConstructorMembersProcessed() { return status & (unsigned short) 0x0001; }
void MarkMethodMembersProcessed() { status |= (unsigned short) 0x0002; }
bool MethodMembersProcessed() { return status & (unsigned short) 0x0002; }
void MarkFieldMembersProcessed() { status |= (unsigned short) 0x0004; }
bool FieldMembersProcessed() { return status & (unsigned short) 0x0004; }
void MarkLocalClassProcessingCompleted() { status |= (unsigned short) 0x0008; }
bool LocalClassProcessingCompleted() { return status & (unsigned short) 0x0008; }
void MarkSourcePending() { status |= (unsigned short) 0x0010; }
void MarkSourceNoLongerPending() { status &= (~ ((unsigned short) 0x0010)); }
bool SourcePending() { return status & (unsigned short) 0x0010; }
void MarkAnonymous() { status |= (unsigned short) 0x0020; }
bool Anonymous() { return status & (unsigned short) 0x0020; }
void MarkHeaderProcessed() { status |= (unsigned short) 0x0040; }
bool HeaderProcessed() { return status & (unsigned short) 0x0040; }
void MarkPrimitive() { status |= (unsigned short) 0x0080; }
bool Primitive() { return status & (unsigned short) 0x0080; }
void MarkBad()
{
SetACC_PUBLIC();
status |= (unsigned short) 0x0100;
MarkHeaderProcessed();
MarkConstructorMembersProcessed();
MarkMethodMembersProcessed();
MarkFieldMembersProcessed();
MarkLocalClassProcessingCompleted();
MarkSourceNoLongerPending();
return;
}
bool Bad() { return status & (unsigned short) 0x0100; }
void MarkCircular()
{
status |= (unsigned short) 0x0200;
MarkBad();
return;
}
void MarkNonCircular() { status &= (~ ((unsigned short) 0x0200)); }
bool Circular() { return status & (unsigned short) 0x0200; }
void ProcessNestedTypeSignatures(Semantic *, LexStream::TokenIndex);
bool NestedTypesProcessed() { return nested_type_signatures == NULL; }
int NumNestedTypeSignatures()
{
return (nested_type_signatures ? nested_type_signatures -> Length() : 0);
}
char *NestedTypeSignature(int i)
{
return (*nested_type_signatures)[i];
}
void AddNestedTypeSignature(char *signature_, int length)
{
char *signature = new char[length + 1];
strncpy(signature, signature_, length);
signature[length] = U_NULL;
if (! nested_type_signatures)
nested_type_signatures = new Tuple<char *>(8);
nested_type_signatures -> Next() = signature;
}
inline void SetSymbolTable(int);
inline SymbolTable *Table();
int NumVariableSymbols();
VariableSymbol *VariableSym(int);
int NumMethodSymbols();
MethodSymbol *MethodSym(int);
int NumTypeSymbols();
TypeSymbol *TypeSym(int);
inline TypeSymbol *InsertAnonymousTypeSymbol(NameSymbol *);
inline TypeSymbol *FindTypeSymbol(NameSymbol *);
inline TypeSymbol *InsertNestedTypeSymbol(NameSymbol *);
inline MethodSymbol *FindConstructorSymbol();
inline MethodSymbol *InsertConstructorSymbol(NameSymbol *);
inline void InsertConstructorSymbol(MethodSymbol *);
inline MethodSymbol *FindMethodSymbol(NameSymbol *);
inline VariableSymbol *FindVariableSymbol(NameSymbol *);
inline VariableSymbol *InsertVariableSymbol(NameSymbol *);
inline void InsertVariableSymbol(VariableSymbol *);
inline MethodSymbol *InsertMethodSymbol(NameSymbol *);
inline void InsertMethodSymbol(MethodSymbol *);
inline MethodSymbol *Overload(MethodSymbol *);
inline void Overload(MethodSymbol *, MethodSymbol *);
inline MethodSymbol *LocalConstructorOverload(MethodSymbol *);
MethodSymbol *FindOverloadMethod(MethodSymbol *, AstMethodDeclarator *);
inline void CompressSpace();
private:
NameSymbol *external_name_symbol;
SymbolTable *table;
unsigned short status;
PackageSymbol *package;
char *class_name;
void SetClassName();
TypeSymbol *class_literal_class;
MethodSymbol *class_literal_method;
Utf8LiteralValue *class_literal_name;
//
// For a local type, when we first encounter an embedded call
// to one of its constructors or a constructor of one of its inner
// types, either via a ClassInstanceCreation or an ExplicitConstructorInvocation,
// we record it and resolve it after we have computed all necessary
// information about the type and its inner types.
//
Tuple<SemanticEnvironment *> *local_constructor_call_environments;
//
// When an inner class tries to access a private member of one of its enclosing
// classes, one (or two) access method(s) to read (and/or write) the private member
// is (are) generated.
//
Tuple<MethodSymbol *> *private_access_methods;
Tuple<MethodSymbol *> *private_access_constructors;
//
// For an accessible inner class the first elememt in this array
// identifies the "this$0" pointer of the containing type. For a local
// class, in addition to the this$0 pointer (if it is needed), all local
// variables that are referred to in the local type are passed as argument
// to the local type and copied in the constructor into a local field. These
// local variables are stored in constructor_parameters.
//
// The array enclosing_instances is there for optimization purposes.
// If this type is deeply nested within several other types and it makes
// references to members in the enclosing types, then it might
// be useful to keep a reference to each of these enclosing
// instances in the form of this$0, this$1, this$2, ...
//
// The array class_identities is used to store static variables of type Class
// that contain the proper value for a given type.
//
Tuple<VariableSymbol *> *constructor_parameters;
Tuple<MethodSymbol *> *generated_constructors;
Tuple<VariableSymbol *> *enclosing_instances;
Tuple<VariableSymbol *> *class_literals;
Tuple<char *> *nested_type_signatures;
//
// The inner types that appear immediately within this type in the order
// in which they should be processed (compiled).
Tuple<TypeSymbol *> *nested_types;
//
// The interfaces that were declared in the header of the type.
//
Tuple<TypeSymbol *> *interfaces;
//
// The anonymous types that were declared in this type.
//
Tuple<TypeSymbol *> *anonymous_types;
//
// The arrays of this type that were declared.
//
Tuple<TypeSymbol *> *array;
inline int NumArrays()
{
return (array ? array -> Length() : 0);
}
inline TypeSymbol *Array(int i)
{
return (*array)[i];
}
inline void AddArrayType(TypeSymbol *type_symbol)
{
if (! array)
array = new Tuple<TypeSymbol *>(4);
array -> Next() = type_symbol;
}
};
class VariableSymbol : public Symbol, public AccessFlags
{
public:
Ast *declarator;
NameSymbol *name_symbol;
Symbol *owner;
LiteralValue *initial_value;
int constant_pool_index,
constant_pool_class,
local_program_counter;
VariableSymbol *accessed_local;
MethodSymbol *read_method,
*write_method;
virtual wchar_t *Name() { return name_symbol -> Name(); }
virtual int NameLength() { return name_symbol -> NameLength(); }
virtual NameSymbol *Identity() { return name_symbol; }
char *Utf8Name() { return (char *) (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL); }
int Utf8NameLength() { return (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0); }
void SetExternalIdentity(NameSymbol *external_name_symbol_) { external_name_symbol = external_name_symbol_; }
NameSymbol *ExternalIdentity()
{
return (external_name_symbol ? external_name_symbol : name_symbol);
}
wchar_t *ExternalName()
{
return (external_name_symbol ? external_name_symbol -> Name() : name_symbol -> Name());
}
int ExternalNameLength()
{
return (external_name_symbol ? external_name_symbol -> NameLength() : name_symbol -> NameLength());
}
char *ExternalUtf8Name()
{
return (char *) (external_name_symbol ? external_name_symbol -> Utf8_literal -> value
: (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL));
}
int ExternalUtf8NameLength()
{
return (external_name_symbol ? (external_name_symbol -> Utf8_literal ? external_name_symbol -> Utf8_literal -> length : 0)
: (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0));
}
VariableSymbol(NameSymbol *name_symbol_) : declarator(NULL),
name_symbol(name_symbol_),
external_name_symbol(NULL),
owner(NULL),
type_(NULL),
signature_string(NULL),
initial_value(NULL),
local_variable_index_(-1),
constant_pool_index(0),
constant_pool_class(0),
local_program_counter(0),
accessed_local(NULL),
read_method(NULL),
write_method(NULL),
status(0)
{
Symbol::_kind = VARIABLE;
}
virtual ~VariableSymbol() { delete [] signature_string; }
void SetFlags(AccessFlags variable_access) { access_flags = variable_access.access_flags; }
void SetOwner(Symbol *owner_) { owner = owner_; }
void SetLocalVariableIndex(int index)
{
local_variable_index_ = index;
MarkComplete();
}
int LocalVariableIndex() { return local_variable_index_; }
bool IsTyped()
{
return type_ != NULL;
}
void SetType(TypeSymbol *_type)
{
type_ = _type;
}
void ProcessVariableSignature(Semantic *, LexStream::TokenIndex);
TypeSymbol *Type(Semantic *sem = NULL, LexStream::TokenIndex tok = 0)
{
if (! type_)
ProcessVariableSignature(sem, tok);
assert(type_);
return type_;
}
void SetSignatureString(char *signature_, int length)
{
signature_string = new char[length + 1];
strncpy(signature_string, signature_, length);
signature_string[length] = U_NULL;
}
bool IsLocal() { return owner -> MethodCast() != NULL; } // is variable a local variable?
bool IsLocal(MethodSymbol *method) { return owner == method; } // is variable local to a particular method ?
bool IsFinal(TypeSymbol *type) { return (owner == type && ACC_FINAL()); }
//
// These functions are used to identify when the declaration of a field in the body of a class is
// complete.
//
void MarkIncomplete() { status &= (~((unsigned char) 0x01)); }
void MarkComplete() { status |= (unsigned char) 0x01; }
bool IsDeclarationComplete() { return status & (unsigned char) 0x01; }
void MarkNotDefinitelyAssigned() { status &= (~((unsigned char) 0x02)); }
void MarkDefinitelyAssigned() { status |= (unsigned char) 0x02; }
bool IsDefinitelyAssigned() { return status & (unsigned char) 0x02; }
void MarkPossiblyAssigned() { status |= (unsigned char) 0x04; }
bool IsPossiblyAssigned() { return status & (unsigned char) 0x04; }
void MarkSynthetic() { status |= (unsigned char) 0x08; }
bool IsSynthetic() { return status & (unsigned char) 0x08; }
private:
NameSymbol *external_name_symbol;
unsigned char status;
int local_variable_index_;
TypeSymbol *type_;
char *signature_string;
};
class BlockSymbol : public Symbol
{
public:
int max_variable_index,
synchronized_variable_index,
try_variable_index;
BlockSymbol(int hash_size);
virtual ~BlockSymbol();
int NumVariableSymbols();
VariableSymbol *VariableSym(int);
inline VariableSymbol *FindVariableSymbol(NameSymbol *);
inline VariableSymbol *InsertVariableSymbol(NameSymbol *);
inline void InsertVariableSymbol(VariableSymbol *);
inline BlockSymbol *InsertBlockSymbol(int);
inline void CompressSpace();
inline SymbolTable *Table();
private:
SymbolTable *table;
};
class LabelSymbol : public Symbol
{
public:
AstBlock *block; // the block that is labeled by this symbol
NameSymbol *name_symbol;
int nesting_level;
virtual wchar_t *Name() { return name_symbol -> Name(); }
virtual int NameLength() { return name_symbol -> NameLength(); }
virtual NameSymbol *Identity() { return name_symbol; }
char *Utf8Name() { return (char *) (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL); }
int Utf8NameLength() { return (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0); }
LabelSymbol(NameSymbol *name_symbol_) : block(NULL),
nesting_level(0),
name_symbol(name_symbol_)
{
Symbol::_kind = LABEL;
}
virtual ~LabelSymbol() {}
private:
};
class SymbolTable
{
public:
enum
{
DEFAULT_HASH_SIZE = 13,
MAX_HASH_SIZE = 1021
};
int NumAnonymousSymbols()
{
return (anonymous_symbol_pool ? anonymous_symbol_pool -> Length() : 0);
}
TypeSymbol *AnonymousSym(int i)
{
return (*anonymous_symbol_pool)[i];
}
void AddAnonymousSymbol(TypeSymbol *symbol)
{
if (! anonymous_symbol_pool)
anonymous_symbol_pool = new ConvertibleArray<TypeSymbol *>(256);
anonymous_symbol_pool -> Next() = symbol;
}
int NumTypeSymbols()
{
return (type_symbol_pool ? type_symbol_pool -> Length() : 0);
}
TypeSymbol *&TypeSym(int i)
{
return (*type_symbol_pool)[i];
}
void AddTypeSymbol(TypeSymbol *symbol)
{
if (! type_symbol_pool)
type_symbol_pool = new ConvertibleArray<TypeSymbol *>(256);
type_symbol_pool -> Next() = symbol;
}
int NumMethodSymbols()
{
return (method_symbol_pool ? method_symbol_pool -> Length() : 0);
}
MethodSymbol *MethodSym(int i)
{
return (*method_symbol_pool)[i];
}
void AddMethodSymbol(MethodSymbol *symbol)
{
if (! method_symbol_pool)
method_symbol_pool = new ConvertibleArray<MethodSymbol *>(256);
method_symbol_pool -> Next() = symbol;
}
int NumVariableSymbols()
{
return (variable_symbol_pool ? variable_symbol_pool -> Length() : 0);
}
VariableSymbol *VariableSym(int i)
{
return (*variable_symbol_pool)[i];
}
void AddVariableSymbol(VariableSymbol *symbol)
{
if (! variable_symbol_pool)
variable_symbol_pool = new ConvertibleArray<VariableSymbol *>(256);
variable_symbol_pool -> Next() = symbol;
}
int NumOtherSymbols()
{
return (other_symbol_pool ? other_symbol_pool -> Length() : 0);
}
Symbol *OtherSym(int i)
{
return (*other_symbol_pool)[i];
}
void AddOtherSymbol(Symbol *symbol)
{
if (! other_symbol_pool)
other_symbol_pool = new ConvertibleArray<Symbol *>(256);
other_symbol_pool -> Next() = symbol;
}
SymbolTable(int hash_size_ = DEFAULT_HASH_SIZE);
~SymbolTable();
inline void CompressSpace()
{
if (anonymous_symbol_pool)
(void) anonymous_symbol_pool -> Array();
if (method_symbol_pool)
(void) method_symbol_pool -> Array();
if (variable_symbol_pool)
(void) variable_symbol_pool -> Array();
if (other_symbol_pool)
(void) other_symbol_pool -> Array();
return;
}
private:
Tuple<TypeSymbol *> *type_symbol_pool; // This array should not be convertible. See SymbolTable::DeleteTypeSymbol
ConvertibleArray<TypeSymbol *> *anonymous_symbol_pool;
ConvertibleArray<MethodSymbol *> *method_symbol_pool;
ConvertibleArray<VariableSymbol *> *variable_symbol_pool;
ConvertibleArray<Symbol *> *other_symbol_pool;
Symbol **base;
int hash_size;
static int primes[];
int prime_index;
int Size()
{
return NumAnonymousSymbols() +
NumTypeSymbols() +
NumMethodSymbols() +
NumVariableSymbols() +
NumOtherSymbols();
}
void Rehash();
MethodSymbol *constructor;
public:
inline PathSymbol *InsertPathSymbol(NameSymbol *, DirectorySymbol *);
inline PathSymbol *FindPathSymbol(NameSymbol *);
inline DirectorySymbol *InsertDirectorySymbol(NameSymbol *, Symbol *);
inline DirectorySymbol *InsertAndReadDirectorySymbol(NameSymbol *, Symbol *);
inline DirectorySymbol *FindDirectorySymbol(NameSymbol *);
inline FileSymbol *InsertFileSymbol(NameSymbol *);
inline FileSymbol *FindFileSymbol(NameSymbol *);
inline PackageSymbol *InsertPackageSymbol(NameSymbol *, PackageSymbol *);
inline PackageSymbol *FindPackageSymbol(NameSymbol *);
inline TypeSymbol *InsertAnonymousTypeSymbol(NameSymbol *);
inline TypeSymbol *InsertSystemTypeSymbol(NameSymbol *);
inline TypeSymbol *InsertOuterTypeSymbol(NameSymbol *);
inline TypeSymbol *InsertNestedTypeSymbol(NameSymbol *);
inline void DeleteTypeSymbol(TypeSymbol *);
inline void DeleteAnonymousTypes();
inline TypeSymbol *FindTypeSymbol(NameSymbol *);
inline MethodSymbol *InsertMethodSymbol(NameSymbol *);
inline MethodSymbol *InsertConstructorSymbol(NameSymbol *);
inline void InsertMethodSymbol(MethodSymbol *);
inline void InsertConstructorSymbol(MethodSymbol *);
inline MethodSymbol *FindMethodSymbol(NameSymbol *);
inline MethodSymbol *FindConstructorSymbol();
inline VariableSymbol *InsertVariableSymbol(NameSymbol *);
inline void InsertVariableSymbol(VariableSymbol *);
inline VariableSymbol *FindVariableSymbol(NameSymbol *);
inline LabelSymbol *InsertLabelSymbol(NameSymbol *);
inline LabelSymbol *FindLabelSymbol(NameSymbol *);
inline BlockSymbol *InsertBlockSymbol(int);
inline MethodSymbol *Overload(MethodSymbol *);
inline void Overload(MethodSymbol *, MethodSymbol *);
inline MethodSymbol *LocalConstructorOverload(MethodSymbol *);
MethodSymbol *FindOverloadMethod(MethodSymbol *, AstMethodDeclarator *);
};
inline int TypeSymbol::NumVariableSymbols() { return (table ? table -> NumVariableSymbols() : 0); }
inline int BlockSymbol::NumVariableSymbols() { return (table ? table -> NumVariableSymbols() : 0); }
inline VariableSymbol *TypeSymbol::VariableSym(int i) { return table -> VariableSym(i); }
inline VariableSymbol *BlockSymbol::VariableSym(int i) { return table -> VariableSym(i); }
inline int TypeSymbol::NumMethodSymbols() { return (table ? table -> NumMethodSymbols() : 0); }
inline MethodSymbol *TypeSymbol::MethodSym(int i) { return table -> MethodSym(i); }
inline int TypeSymbol::NumTypeSymbols() { return (table ? table -> NumTypeSymbols() : 0); }
inline TypeSymbol *TypeSymbol::TypeSym(int i) { return table -> TypeSym(i); }
inline void TypeSymbol::CompressSpace() { if (table) table -> CompressSpace(); }
inline void BlockSymbol::CompressSpace() { if (table) table -> CompressSpace(); }
inline PathSymbol *SymbolTable::InsertPathSymbol(NameSymbol *name_symbol, DirectorySymbol *directory_symbol)
{
assert(base);
PathSymbol *symbol = new PathSymbol(name_symbol);
directory_symbol -> owner = symbol;
symbol -> root_directory = directory_symbol;
AddOtherSymbol(symbol);
int k = name_symbol -> index % hash_size;
symbol -> next = base[k];
base[k] = symbol;
//
// If the set is "adjustable" and the number of unique elements in it exceeds
// 2 times the size of the base, and we have not yet reached the maximum
// allowable size for a base, reallocate a larger base and rehash the elements.
//
if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1)))
Rehash();
return symbol;
}
inline PathSymbol *SymbolTable::FindPathSymbol(NameSymbol *name_symbol)
{
assert(base);
for (Symbol *symbol = base[name_symbol -> index % hash_size]; symbol; symbol = symbol -> next)
{
if (name_symbol == symbol -> Identity())
return (PathSymbol *) symbol;
}
return (PathSymbol *) NULL;
}
inline DirectorySymbol *SymbolTable::InsertDirectorySymbol(NameSymbol *name_symbol, Symbol *owner)
{
assert(base);
DirectorySymbol *symbol = new DirectorySymbol(name_symbol, owner);
AddOtherSymbol(symbol);
int k = name_symbol -> index % hash_size;
symbol -> next = base[k];
base[k] = symbol;
//
// If the set is "adjustable" and the number of unique elements in it exceeds
// 2 times the size of the base, and we have not yet reached the maximum
// allowable size for a base, reallocate a larger base and rehash the elements.
//
if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1)))
Rehash();
return symbol;
}
inline DirectorySymbol *SymbolTable::InsertAndReadDirectorySymbol(NameSymbol *name_symbol, Symbol *owner)
{
DirectorySymbol *subdirectory_symbol = InsertDirectorySymbol(name_symbol, owner);
subdirectory_symbol -> ResetDirectory();
return subdirectory_symbol;
}
inline DirectorySymbol *DirectorySymbol::InsertDirectorySymbol(NameSymbol *name_symbol)
{
DirectorySymbol *subdirectory_symbol = Table() -> InsertDirectorySymbol(name_symbol, this);
this -> subdirectories.Next() = subdirectory_symbol;
return subdirectory_symbol;
}
inline DirectorySymbol *DirectorySymbol::InsertAndReadDirectorySymbol(NameSymbol *name_symbol)
{
DirectorySymbol *subdirectory_symbol = Table() -> InsertAndReadDirectorySymbol(name_symbol, this);
this -> subdirectories.Next() = subdirectory_symbol;
return subdirectory_symbol;
}
inline DirectorySymbol *SymbolTable::FindDirectorySymbol(NameSymbol *name_symbol)
{
assert(base);
for (Symbol *symbol = base[name_symbol -> index % hash_size]; symbol; symbol = symbol -> next)
{
if (name_symbol == symbol -> Identity())
{
DirectorySymbol *directory_symbol = symbol -> DirectoryCast();
if (directory_symbol)
return directory_symbol;
}
}
return (DirectorySymbol *) NULL;
}
inline DirectorySymbol *DirectorySymbol::FindDirectorySymbol(NameSymbol *name_symbol)
{
return (table ? table -> FindDirectorySymbol(name_symbol) : (DirectorySymbol *) NULL);
}
inline FileSymbol *SymbolTable::InsertFileSymbol(NameSymbol *name_symbol)
{
assert(base);
FileSymbol *symbol = new FileSymbol(name_symbol);
AddOtherSymbol(symbol);
int k = name_symbol -> index % hash_size;
symbol -> next = base[k];
base[k] = symbol;
//
// If the set is "adjustable" and the number of unique elements in it exceeds
// 2 times the size of the base, and we have not yet reached the maximum
// allowable size for a base, reallocate a larger base and rehash the elements.
//
if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1)))
Rehash();
return symbol;
}
inline FileSymbol *DirectorySymbol::InsertFileSymbol(NameSymbol *name_symbol)
{
return Table() -> InsertFileSymbol(name_symbol);
}
inline FileSymbol *SymbolTable::FindFileSymbol(NameSymbol *name_symbol)
{
assert(base);
for (Symbol *symbol = base[name_symbol -> index % hash_size]; symbol; symbol = symbol -> next)
{
if (name_symbol == symbol -> Identity())
{
FileSymbol *file_symbol = symbol -> FileCast();
if (file_symbol)
return file_symbol;
}
}
return (FileSymbol *) NULL;
}
inline FileSymbol *DirectorySymbol::FindFileSymbol(NameSymbol *name_symbol)
{
return (table ? table -> FindFileSymbol(name_symbol) : (FileSymbol *) NULL);
}
inline PackageSymbol *SymbolTable::InsertPackageSymbol(NameSymbol *name_symbol, PackageSymbol *owner)
{
assert(base);
PackageSymbol *symbol = new PackageSymbol(name_symbol, owner);
AddOtherSymbol(symbol);
int k = name_symbol -> index % hash_size;
symbol -> next = base[k];
base[k] = symbol;
//
// If the set is "adjustable" and the number of unique elements in it exceeds
// 2 times the size of the base, and we have not yet reached the maximum
// allowable size for a base, reallocate a larger base and rehash the elements.
//
if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1)))
Rehash();
return symbol;
}
inline PackageSymbol *PackageSymbol::InsertPackageSymbol(NameSymbol *name_symbol)
{
return Table() -> InsertPackageSymbol(name_symbol, this);
}
inline PackageSymbol *SymbolTable::FindPackageSymbol(NameSymbol *name_symbol)
{
assert(base);
for (Symbol *symbol = base[name_symbol -> index % hash_size]; symbol; symbol = symbol -> next)
{
if (name_symbol == symbol -> Identity())
{
PackageSymbol *package_symbol = symbol -> PackageCast();
if (package_symbol)
return package_symbol;
}
}
return (PackageSymbol *) NULL;
}
inline PackageSymbol *PackageSymbol::FindPackageSymbol(NameSymbol *name_symbol)
{
return (table ? table -> FindPackageSymbol(name_symbol) : (PackageSymbol *) NULL);
}
inline TypeSymbol *SymbolTable::InsertAnonymousTypeSymbol(NameSymbol *name_symbol)
{
TypeSymbol *symbol = new TypeSymbol(name_symbol);
AddAnonymousSymbol(symbol);
return symbol;
}
inline TypeSymbol *TypeSymbol::InsertAnonymousTypeSymbol(NameSymbol *name_symbol)
{
return Table() -> InsertAnonymousTypeSymbol(name_symbol);
}
inline TypeSymbol *SymbolTable::InsertSystemTypeSymbol(NameSymbol *name_symbol)
{
assert(base);
TypeSymbol *symbol = new TypeSymbol(name_symbol);
symbol -> pool_index = NumTypeSymbols();
AddTypeSymbol(symbol);
int k = name_symbol -> index % hash_size;
symbol -> next = base[k];
base[k] = symbol;
//
// If the set is "adjustable" and the number of unique elements in it exceeds
// 2 times the size of the base, and we have not yet reached the maximum
// allowable size for a base, reallocate a larger base and rehash the elements.
//
if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1)))
Rehash();
return symbol;
}
inline TypeSymbol *PackageSymbol::InsertSystemTypeSymbol(NameSymbol *name_symbol)
{
return Table() -> InsertSystemTypeSymbol(name_symbol);
}
inline TypeSymbol *SymbolTable::InsertOuterTypeSymbol(NameSymbol *name_symbol)
{
assert(base);
TypeSymbol *symbol = new TypeSymbol(name_symbol);
symbol -> pool_index = NumTypeSymbols();
AddTypeSymbol(symbol);
int k = name_symbol -> index % hash_size;
symbol -> next = base[k];
base[k] = symbol;
//
// If the set is "adjustable" and the number of unique elements in it exceeds
// 2 times the size of the base, and we have not yet reached the maximum
// allowable size for a base, reallocate a larger base and rehash the elements.
//
if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1)))
Rehash();
return symbol;
}
inline TypeSymbol *PackageSymbol::InsertOuterTypeSymbol(NameSymbol *name_symbol)
{
return Table() -> InsertOuterTypeSymbol(name_symbol);
}
inline TypeSymbol *SymbolTable::InsertNestedTypeSymbol(NameSymbol *name_symbol)
{
assert(base);
TypeSymbol *symbol = new TypeSymbol(name_symbol);
symbol -> pool_index = NumTypeSymbols();
AddTypeSymbol(symbol);
int k = name_symbol -> index % hash_size;
symbol -> next = base[k];
base[k] = symbol;
//
// If the set is "adjustable" and the number of unique elements in it exceeds
// 2 times the size of the base, and we have not yet reached the maximum
// allowable size for a base, reallocate a larger base and rehash the elements.
//
if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1)))
Rehash();
return symbol;
}
inline TypeSymbol *TypeSymbol::InsertNestedTypeSymbol(NameSymbol *name_symbol)
{
return Table() -> InsertNestedTypeSymbol(name_symbol);
}
inline void SymbolTable::DeleteTypeSymbol(TypeSymbol *type)
{
assert(base);
int k = type -> name_symbol -> index % hash_size;
if (type == base[k])
base[k] = type -> next;
else
{
Symbol *previous = base[k];
for (Symbol *symbol = previous -> next; symbol != type; previous = symbol, symbol = symbol -> next)
;
previous -> next = type -> next;
}
int last_index = NumTypeSymbols() - 1;
if (type -> pool_index != last_index)
{// move last element to position previously occupied by element being deleted
TypeSym(last_index) -> pool_index = type -> pool_index;
TypeSym(type -> pool_index) = TypeSym(last_index);
}
type_symbol_pool -> Reset(last_index); // remove last slot in symbol_pool
delete type;
return;
}
inline void PackageSymbol::DeleteTypeSymbol(TypeSymbol *type)
{
if (table)
table -> DeleteTypeSymbol(type);
}
inline void SymbolTable::DeleteAnonymousTypes()
{
for (int i = 0; i < NumAnonymousSymbols(); i++)
delete AnonymousSym(i);
delete anonymous_symbol_pool;
anonymous_symbol_pool = NULL;
return;
}
inline void TypeSymbol::DeleteAnonymousTypes()
{
delete anonymous_types;
anonymous_types = NULL;
if (table)
table -> DeleteAnonymousTypes();
}
inline TypeSymbol *SymbolTable::FindTypeSymbol(NameSymbol *name_symbol)
{
assert(base);
for (Symbol *symbol = base[name_symbol -> index % hash_size]; symbol; symbol = symbol -> next)
{
if (name_symbol == symbol -> Identity())
{
TypeSymbol *type = symbol -> TypeCast();
if (type)
return type;
}
}
return (TypeSymbol *) NULL;
}
inline TypeSymbol *PackageSymbol::FindTypeSymbol(NameSymbol *name_symbol)
{
return (table ? table -> FindTypeSymbol(name_symbol) : (TypeSymbol *) NULL);
}
inline TypeSymbol *TypeSymbol::FindTypeSymbol(NameSymbol *name_symbol)
{
return (table ? table -> FindTypeSymbol(name_symbol) : (TypeSymbol *) NULL);
}
inline MethodSymbol *SymbolTable::InsertMethodSymbol(NameSymbol *name_symbol)
{
assert(base);
MethodSymbol *symbol = new MethodSymbol(name_symbol);
AddMethodSymbol(symbol);
int k = name_symbol -> index % hash_size;
symbol -> next = base[k];
base[k] = symbol;
//
// If the set is "adjustable" and the number of unique elements in it exceeds
// 2 times the size of the base, and we have not yet reached the maximum
// allowable size for a base, reallocate a larger base and rehash the elements.
//
if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1)))
Rehash();
return symbol;
}
inline MethodSymbol *TypeSymbol::InsertMethodSymbol(NameSymbol *name_symbol)
{
return Table() -> InsertMethodSymbol(name_symbol);
}
inline MethodSymbol *SymbolTable::InsertConstructorSymbol(NameSymbol *name_symbol)
{
assert(! constructor);
this -> constructor = InsertMethodSymbol(name_symbol);
return this -> constructor;
}
inline MethodSymbol *TypeSymbol::InsertConstructorSymbol(NameSymbol *name_symbol)
{
return Table() -> InsertConstructorSymbol(name_symbol);
}
inline void SymbolTable::InsertMethodSymbol(MethodSymbol *method_symbol)
{
assert(base);
AddMethodSymbol(method_symbol);
int k = method_symbol -> name_symbol -> index % hash_size;
method_symbol -> next = base[k];
base[k] = method_symbol;
//
// If the set is "adjustable" and the number of unique elements in it exceeds
// 2 times the size of the base, and we have not yet reached the maximum
// allowable size for a base, reallocate a larger base and rehash the elements.
//
if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1)))
Rehash();
return;
}
inline void TypeSymbol::InsertMethodSymbol(MethodSymbol *method_symbol)
{
Table() -> InsertMethodSymbol(method_symbol);
}
inline void SymbolTable::InsertConstructorSymbol(MethodSymbol *method_symbol)
{
assert(! constructor);
this -> constructor = method_symbol;
InsertMethodSymbol(method_symbol);
}
inline void TypeSymbol::InsertConstructorSymbol(MethodSymbol *method_symbol)
{
Table() -> InsertConstructorSymbol(method_symbol);
}
inline MethodSymbol *SymbolTable::FindMethodSymbol(NameSymbol *name_symbol)
{
assert(base);
for (Symbol *symbol = base[name_symbol -> index % hash_size]; symbol; symbol = symbol -> next)
{
if (name_symbol == symbol -> Identity())
{
MethodSymbol *method = symbol -> MethodCast();
if (method)
return method;
}
}
return (MethodSymbol *) NULL;
}
inline MethodSymbol *TypeSymbol::FindMethodSymbol(NameSymbol *name_symbol)
{
return (table ? table -> FindMethodSymbol(name_symbol) : (MethodSymbol *) NULL);
}
inline MethodSymbol *SymbolTable::FindConstructorSymbol()
{
return this -> constructor;
}
inline MethodSymbol *TypeSymbol::FindConstructorSymbol()
{
return (table ? table -> FindConstructorSymbol() : (MethodSymbol *) NULL);
}
inline VariableSymbol *SymbolTable::InsertVariableSymbol(NameSymbol *name_symbol)
{
assert(base);
VariableSymbol *symbol = new VariableSymbol(name_symbol);
AddVariableSymbol(symbol);
int k = name_symbol -> index % hash_size;
symbol -> next = base[k];
base[k] = symbol;
//
// If the set is "adjustable" and the number of unique elements in it exceeds
// 2 times the size of the base, and we have not yet reached the maximum
// allowable size for a base, reallocate a larger base and rehash the elements.
//
if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1)))
Rehash();
return symbol;
}
inline VariableSymbol *TypeSymbol::InsertVariableSymbol(NameSymbol *name_symbol)
{
return Table() -> InsertVariableSymbol(name_symbol);
}
inline VariableSymbol *BlockSymbol::InsertVariableSymbol(NameSymbol *name_symbol)
{
return Table() -> InsertVariableSymbol(name_symbol);
}
inline void SymbolTable::InsertVariableSymbol(VariableSymbol *variable_symbol)
{
assert(base);
AddVariableSymbol(variable_symbol);
int k = variable_symbol -> name_symbol -> index % hash_size;
variable_symbol -> next = base[k];
base[k] = variable_symbol;
//
// If the set is "adjustable" and the number of unique elements in it exceeds
// 2 times the size of the base, and we have not yet reached the maximum
// allowable size for a base, reallocate a larger base and rehash the elements.
//
if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1)))
Rehash();
return;
}
inline void TypeSymbol::InsertVariableSymbol(VariableSymbol *variable_symbol)
{
Table() -> InsertVariableSymbol(variable_symbol);
}
inline void BlockSymbol::InsertVariableSymbol(VariableSymbol *variable_symbol)
{
Table() -> InsertVariableSymbol(variable_symbol);
}
inline VariableSymbol *SymbolTable::FindVariableSymbol(NameSymbol *name_symbol)
{
assert(base);
for (Symbol *symbol = base[name_symbol -> index % hash_size]; symbol; symbol = symbol -> next)
{
if (name_symbol == symbol -> Identity())
{
VariableSymbol *variable_symbol = symbol -> VariableCast();
if (variable_symbol)
return variable_symbol;
}
}
return (VariableSymbol *) NULL;
}
inline VariableSymbol *TypeSymbol::FindVariableSymbol(NameSymbol *name_symbol)
{
return (table ? table -> FindVariableSymbol(name_symbol) : (VariableSymbol *) NULL);
}
inline VariableSymbol *BlockSymbol::FindVariableSymbol(NameSymbol *name_symbol)
{
return (table ? table -> FindVariableSymbol(name_symbol) : (VariableSymbol *) NULL);
}
inline LabelSymbol *SymbolTable::InsertLabelSymbol(NameSymbol *name_symbol)
{
assert(base);
LabelSymbol *symbol = new LabelSymbol(name_symbol);
AddOtherSymbol(symbol);
int k = name_symbol -> index % hash_size;
symbol -> next = base[k];
base[k] = symbol;
//
// as only one label can be inserted in any given symboltable,
// we don't need to try to rehash here !
//
return symbol;
}
inline LabelSymbol *SymbolTable::FindLabelSymbol(NameSymbol *name_symbol)
{
assert(base);
for (Symbol *symbol = base[name_symbol -> index % hash_size]; symbol; symbol = symbol -> next)
{
if (name_symbol == symbol -> Identity())
{
LabelSymbol *label = symbol -> LabelCast();
if (label)
return label;
}
}
return (LabelSymbol *) NULL;
}
inline BlockSymbol *SymbolTable::InsertBlockSymbol(int hash_size = 0)
{
BlockSymbol *symbol = new BlockSymbol(hash_size);
AddOtherSymbol(symbol);
return symbol;
}
inline BlockSymbol *BlockSymbol::InsertBlockSymbol(int hash_size = 0)
{
return Table() -> InsertBlockSymbol(hash_size);
}
inline MethodSymbol *SymbolTable::Overload(MethodSymbol *base_method)
{
MethodSymbol *overload = new MethodSymbol(base_method -> Identity());
AddMethodSymbol(overload);
overload -> next = overload; // mark overloaded method
overload -> next_method = base_method -> next_method;
base_method -> next_method = overload;
return overload;
}
inline MethodSymbol *TypeSymbol::Overload(MethodSymbol *base_method)
{
assert(table);
return table -> Overload(base_method);
}
inline void SymbolTable::Overload(MethodSymbol *base_method, MethodSymbol *overload)
{
AddMethodSymbol(overload);
overload -> next = overload; // mark overloaded method
overload -> next_method = base_method -> next_method;
base_method -> next_method = overload;
return;
}
inline void TypeSymbol::Overload(MethodSymbol *base_method, MethodSymbol *overload)
{
assert(table);
table -> Overload(base_method, overload);
}
inline MethodSymbol *SymbolTable::LocalConstructorOverload(MethodSymbol *base_method)
{
MethodSymbol *overload = new MethodSymbol(base_method -> Identity());
AddMethodSymbol(overload);
overload -> next = overload; // mark overloaded method
overload -> SetGeneratedLocalConstructor(base_method);
return overload;
}
inline MethodSymbol *TypeSymbol::LocalConstructorOverload(MethodSymbol *base_method)
{
assert(table);
return table -> LocalConstructorOverload(base_method);
}
inline MethodSymbol *TypeSymbol::FindOverloadMethod(MethodSymbol *base_method, AstMethodDeclarator *method_declarator)
{
return (table ? table -> FindOverloadMethod(base_method, method_declarator) : (MethodSymbol *) NULL);
}
inline SymbolTable *DirectorySymbol::Table()
{
return (table ? table : table = new SymbolTable(101));
}
inline SymbolTable *PackageSymbol::Table()
{
return (table ? table : table = new SymbolTable(101));
}
inline void TypeSymbol::SetSymbolTable(int estimate)
{
if (! table) // If table was not yet allocated, allocate one based on the estimate
table = new SymbolTable(estimate);
}
inline SymbolTable *TypeSymbol::Table()
{
return (table ? table : table = new SymbolTable());
}
inline SymbolTable *BlockSymbol::Table()
{
return (table ? table : table = new SymbolTable());
}
#ifdef UNIX_FILE_SYSTEM
inline bool FileSymbol::IsClassSuffix(char *suffix)
{
return (strncmp(suffix, class_suffix, class_suffix_length) == 0);
}
inline bool FileSymbol::IsJavaSuffix(char *suffix)
{
return (strncmp(suffix, java_suffix, java_suffix_length) == 0);
}
#elif defined(WIN32_FILE_SYSTEM)
inline bool FileSymbol::IsClassSuffix(char *suffix)
{
return Case::StringSegmentEqual(suffix, class_suffix, class_suffix_length);
}
inline bool FileSymbol::IsJavaSuffix(char *suffix)
{
return Case::StringSegmentEqual(suffix, java_suffix, java_suffix_length);
}
#elif defined(AMIGAOS_FILE_SYSTEM)
// Do not use StringSegmentEqual() as in the WIN32 case, because that
// function may check beyond the end of the string, thus possibly causing
// enforcer hits.
inline bool FileSymbol::IsClassSuffix(char *suffix)
{
return (strncasecmp(suffix, class_suffix, class_suffix_length) == 0);
}
inline bool FileSymbol::IsJavaSuffix(char *suffix)
{
return (strncasecmp(suffix, java_suffix, java_suffix_length) == 0);
}
#endif
#endif // ifndef symbol_INCLUDED